
/**
 * @ProjectName: 
 * @Copyright: 2014 lisheng  All Right Reserved.
 * @address: toughheart@163.com
 * @date: 2015年1月13日 下午9:32:11
 * @Description: 本内容未经本人允许禁止使用、转发.
 */
 
package com.ls.fw.search.lucene.server.base;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHitCountCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ls.fw.data.exception.DataException;
import com.ls.fw.search.lucene.bean.SearchCondition;
import com.ls.fw.search.lucene.mapper.DocMapper;
import com.ls.fw.search.lucene.mapper.TopDocMapper;
import com.ls.fw.search.lucene.util.LuceneUtil;


/**
 * 
 * @author lisheng
 * @date 2015年1月13日 下午9:32:11
 * @version V1.0 
 */
public abstract class AbstractBaseServer implements BaseServer{

	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	
	@Override
	public <M> List<M> scan(IndexSearcher searcher,
			final SearchCondition searchCondition, final DocMapper<M> mapper) {
		final List<M> list = new ArrayList<M>();
		this.scan(searcher, searchCondition, new TopDocMapper() {
			
			@Override
			public boolean mapper(IndexSearcher searcher,TopDocs doc, int page) throws DataException {
				try {
					List<M> templist = LuceneUtil.getResult(0, searchCondition.getPageSize()
							, searcher, doc, searchCondition.getShowFields(), mapper);
					if(templist != null){
						list.addAll(templist);
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				return true;
			}
		});
		return list;
	}

	@Override
	public long scan(IndexSearcher searcher, SearchCondition searchCondition,
			TopDocMapper mapper) {
		long start = System.currentTimeMillis();
		long count = 0L, find = 0L;
		final SearchCondition sc = (SearchCondition) searchCondition.clone();
		int page = 1;
		boolean finish = false;
		while(!finish){
			TopDocs topdocs = this.search(searcher, sc);
			if(topdocs != null && topdocs.scoreDocs.length > 0){
				count = topdocs.totalHits;
				find += topdocs.scoreDocs.length;
				sc.setLastPageLastDoc(topdocs.scoreDocs[topdocs.scoreDocs.length-1]);
				finish = !mapper.mapper(searcher,topdocs, page++);
			}else{
				finish = true;
			}
			if(find >= count){
				finish = true;
			}
		}
		long ends = System.currentTimeMillis();
		logger.info("本次scan耗时:"+(ends-start)+"ms");
		return count;
	}

	@Override
	public TopDocs search(IndexSearcher searcher,
			SearchCondition searchCondition) {
		long start = System.currentTimeMillis();
		TopDocs topdocs = null;
		try {
			if(searchCondition.getLastPageLastDoc()!=null){
				if(searchCondition.getSort() != null){
					topdocs = searcher.searchAfter(searchCondition.getLastPageLastDoc()
							, searchCondition.getQuery()
							, searchCondition.getMaxDoc()
							, searchCondition.getSort(), searchCondition.isDoDocScores()
							, searchCondition.isDoMaxScore());
				}else{
					topdocs = searcher.searchAfter(searchCondition.getLastPageLastDoc()
							, searchCondition.getQuery()
							,searchCondition.getMaxDoc());
				}
			}else{
				if(searchCondition.getSort() != null){
					topdocs = searcher.search(searchCondition.getQuery()
							, searchCondition.getMaxDoc()
							, searchCondition.getSort(), searchCondition.isDoDocScores()
							, searchCondition.isDoMaxScore());
				}else{
					topdocs = searcher.search(searchCondition.getQuery()
							 ,searchCondition.getMaxDoc());
				}
			}
		} catch (IOException e) {
			throw new DataException(e.getMessage(), e);
		}
		long ends = System.currentTimeMillis();
		logger.info("本次search耗时:"+(ends-start)+"ms");
		return topdocs;
	}

	
	@Override
	public long count(IndexSearcher searcher, final SearchCondition searchCondition){
		long start = System.currentTimeMillis();
		TotalHitCountCollector c = new TotalHitCountCollector();
	    try {
			searcher.search(searchCondition.getQuery(), c);
		} catch (IOException e) {
			throw new DataException(e.getMessage(), e);
		}
	    long ends = System.currentTimeMillis();
		logger.info("本次count耗时:"+(ends-start)+"ms");
		return c.getTotalHits();
	}
}
